using System;
using System.Collections;
using System.Runtime.CompilerServices;
using jQueryApi;

namespace Nsb.Classes
{
    [IgnoreNamespace]
    public static class Css
    {
        // Doesn't seem to be needed as jQuery.GetCSS("color") seems to get the virtual deep color
        //public static string DeepColor(jQueryObject el)
        //{
        //    string c;
        //    do
        //    {
        //        c = el.GetCSS("color");
        //        Inform.Debug("color {0}", c);
        //        el = el.Parent();
        //    } while (el.Length > 0);
        //    return c;
        //}
        public const string White = "rgba(255, 255, 255, 1)";
        public const string Black = "rgba(0, 0, 0, 1)";

        public static void ResetCss(jQueryObject el)
        {
            if (el == null) return;
            const string deef = "";
            el.CSS(new Dictionary(
                       "color", deef,
                       "background-color", deef,
                       "border-color", deef,
                       "border-size", deef,
                       "font-size", "100%",
                       "font", "inherit",
                       "vertical-align", "baseline"
                       ));
        }

        [AlternateSignature]
        public static extern void Clone(jQueryObject from, jQueryObject to);

        public static void Clone(jQueryObject from, jQueryObject to, string[] props)
        {
            if (props == null)
            {
                to.CSS(from.Plugin<Jewl>().GetStyles());
                return;
            }

            foreach (string p in props)
            {
                to.CSS(p, from.GetCSS(p));
            }
        }

        public static string AlphaPercent(string txt)
        {
            if (txt == null)
                return null;
            Color c = GetColor(txt);
            return (Number.ParseInt(c.opacity*100)).ToString();
        }

        public static bool IsPartialColor(string txt)
        {
            if (txt == null)
                return false;
            Color c = GetColor(txt);
            return c.opacity < 1 && c.opacity > 0;
        }

        public static string RealBgColor(jQueryObject el)
        {
            string c = el.GetCSS("background-color");
            while (Number.ParseInt(AlphaPercent(c)) == 0)
            {
                el = el.Parent();
                if (el == null)
                    return jQuery.Select("body").GetCSS("background-color");
                c = el.GetCSS("background-color");
            }
            return c;
        }

        [AlternateSignature]
        public static extern int BorderWidth(Dictionary css);

        public static int BorderWidth(Dictionary css, int deef)
        {
            string bs = (string) css["border-style"];
            if (bs == null || bs == "none")
                return 0;
            string bwt = (string)(css["border-width"] ?? css["border-left-width"]) ?? (Arguments.Length > 1 ? deef.ToString() : null) ?? "0";
            return Number.ParseInt(bwt);
        }

        [AlternateSignature]
        public static extern int PaddingTop(Dictionary css);

        public static int PaddingTop(Dictionary css, int deef)
        {
            string p = ((bool)(css["padding-top"]) || (bool)(object)deef || (bool)(object)0).ToString();
            return Number.ParseInt(p);
        }

        [AlternateSignature]
        public static extern int PaddingLeft(Dictionary css);

        public static int PaddingLeft(Dictionary css, int deef)
        {
            string p = ((bool)(css["padding-left"]) || (bool)(object)deef || (bool)(object)0).ToString();
            return Number.ParseInt(p);
        }

        [AlternateSignature]
        public static extern int PaddingRight(Dictionary css);

        public static int PaddingRight(Dictionary css, int deef)
        {
            string p = ((bool)(css["padding-right"]) || (bool)(object)deef || (bool)(object)0).ToString();
            return Number.ParseInt(p);
        }

        [AlternateSignature]
        public static extern int PaddingBottom(Dictionary css);

        public static int PaddingBottom(Dictionary css, int deef)
        {
            string p = ((bool)(css["padding-bottom"]) || (bool)(object)deef || (bool)(object)0).ToString();
            return Number.ParseInt(p);
        }

        public static int PaddingHorz(Dictionary css)
        {
            return PaddingLeft(css) + PaddingRight(css);
        }

        public static int PaddingVert(Dictionary css)
        {
            return PaddingTop(css) + PaddingBottom(css);
        }

        public static int OffsetVert(Dictionary css, int deef)
        {
            return PaddingTop(css, deef) + PaddingBottom(css, deef) + BorderWidth(css) * 2;
        }

        public static Color GetColor(string txt)
        {
            Color c = new Color();
            //Inform.Debug("GetColor txt={0}", txt);
            txt = txt == "transparent" ? "rgba(0, 0, 0, 0)" : txt;
            string[] cs = ((RegularExpression) Script.Literal(@"/rgb\s*?\(\s*?(\d+)\s*?,\s*?(\d+)\s*?\,\s*?(\d+)\s*?\)|rgba\s*?\(\s*?(\d+)\s*?,\s*?(\d+)\s*?\,\s*?(\d+)\s*?,\s*?([\d.]+)\s*?\)/")).Exec(txt);
            if (cs == null)
            {
                cs = ((RegularExpression)Script.Literal(@"/#([\da-f])([\da-f])([\da-f])/i")).Exec(txt);
                if (cs == null)
                    cs = ((RegularExpression)Script.Literal(@"/#([\da-f][\da-f])([\da-f][\da-f])([\da-f][\da-f])/i")).Exec(txt);
                if (cs != null)
                {
                    cs[1] = Number.ParseInt(cs[1],16).ToString();
                    cs[2] = Number.ParseInt(cs[2],16).ToString();
                    cs[3] = Number.ParseInt(cs[3],16).ToString();
                }
            }
            if (cs == null)
            {
                c.red = c.green = c.blue = 0;
                c.opacity = 1;
            }
            else if (cs[1] != null)
            {
                c.red = Number.ParseInt(cs[1]);
                c.green = Number.ParseInt(cs[2]);
                c.blue = Number.ParseInt(cs[3]);
                c.opacity = 1;
            }
            else
            {
                c.red = Number.ParseInt(cs[4] ?? "0");
                c.green = Number.ParseInt(cs[5] ?? "0");
                c.blue = Number.ParseInt(cs[6] ?? "0");
                // ReSharper disable PossibleLossOfFraction
                c.opacity = Math.Round(Number.ParseFloat(Script.Value(cs[7], "1"))*100)/100;
                // ReSharper restore PossibleLossOfFraction
            }
            //Inform.Debug("GetColor rgba = {0}, {1}, {2}, {3}", c.red, c.green, c.blue, c.opacity);
            return c;
        }

        public static string Fade(string c, double percent)
        {
            Color cc = GetColor(c);
            cc.opacity = Math.Round(Math.Min(Math.Max(cc.opacity - percent, 0), 1) * 100) / 100;
            return cc.ToString();
        }
    }

    public sealed class Color
    {
        public int blue;
        public int green;
        public double opacity;
        public int red;

#pragma warning disable 108,114
        public string ToString()
#pragma warning restore 108,114
        {
            return "rgba(" + red + ", " + green + ", " + blue + ", " + opacity + ")";
        }
    }
}